package chat.view.dialogs;

import chat.clients.XmppClient;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.PacketExtension;
import swing.bubble.TextBubbleBorder;

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Vector;

import static java.awt.BorderLayout.*;
import static java.awt.Color.*;

public class ChatDialog extends swing.Dialog {
    /**
     *
     */
    private static final long serialVersionUID = -6978345730406749450L;
    private static final String CHAT_STATES_NS = "http://jabber.org/protocol/chatstates";
    private static final String ARCHIVE_NS = "http://jabber.org/protocol/archive";

    private final Chat chat;
    private final MessageEditorPanel messageEditorPanel = new MessageEditorPanel();
    private final XmppClient client;
    private final RosterEntry entry;
    private final HistoryPanel historyPanel = new HistoryPanel();

    public ChatDialog(XmppClient client, final RosterEntry entry) {
        this.client = client;
        this.entry = entry;
        setTitle(entry.getName());
        setLayout(new BorderLayout());
        getContentPane().add(new HeaderPanel(), NORTH);
        getContentPane().add(messageEditorPanel, SOUTH);
        getContentPane().add(historyPanel);

        chat = client.createChat(entry.getUser(), (chat1, message) -> {
            if (message.getBodies().size() > 0)
                historyPanel.add(message);

            if (message.getExtensions().size() == 0) {
                messageEditorPanel.chatStateLabel.setText("");
            } else {
                for (PacketExtension extension : message.getExtensions()) {
                    if (extension.getNamespace().equals(CHAT_STATES_NS))
                        messageEditorPanel.chatStateLabel.setText(entry.getName() + " is " + extension.getElementName());
                    System.out.println(extension.getNamespace() + ", " + extension.getElementName());
                }
            }
        });

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                send();
            }
        });

        pack();
    }

    private void send() {
        if (messageEditorPanel.textField.getText().length() == 0)
            return;

        Message message = new Message(entry.getUser(), Message.Type.chat);
        message.setBody(messageEditorPanel.textField.getText());
        messageEditorPanel.textField.setText("");
        try {
            chat.sendMessage(message);
            historyPanel.add(message);
        } catch (XMPPException e1) {
            popup(e1);
        }

    }

    private class MessageEditorPanel extends JPanel {
        /**
         *
         */
        private static final long serialVersionUID = 2093704814666730558L;
        private final JLabel chatStateLabel = new JLabel();
        private final JTextField textField = new JTextField(20);
        private final JButton sendButton = new JButton("Send");

        private MessageEditorPanel() {
            super(new BorderLayout());
            add(chatStateLabel, NORTH);
            add(sendButton, EAST);
            add(textField);

            sendButton.addActionListener(e -> send());
        }
    }

    private class HistoryPanel extends JScrollPane {

        /**
         *
         */
        private static final long serialVersionUID = -2612054861006369107L;
        private final Vector<Message> vector = new Vector<>();
        private final JList<Message> list = new JList<>(vector);

        private HistoryPanel() {
            setViewportView(list);
            setSize(300, 300);
            setBackground(darkGray);
            list.setCellRenderer((list1, value, index, isSelected, cellHasFocus) -> client.getUser().equals(value.getFrom()) ?
                    new MyBalloon(value) :
                    new OtherBalloon(value));
        }

        public void add(Message message) {
            vector.add(0, message);
            list.setListData(vector);
        }

        public class MyBalloon extends Balloon {
            MyBalloon(Message message) {
                super(message, new TextBubbleBorder(BLACK, 2, 16, 16), yellow);
            }
        }

        public class OtherBalloon extends Balloon {
            public OtherBalloon(Message message) {
                super(message, new TextBubbleBorder(BLACK, 2, 16, 16, false), blue);
            }
        }

        public class Balloon extends JLabel {
            public Balloon(Message message, Border border, Color bg) {
                super(message.getBody());
                setOpaque(true);
                setBorder(border);
                setBackground(bg);
            }

        }
    }

    private class HeaderPanel extends JPanel {

        /**
         *
         */
        private static final long serialVersionUID = -2709786419541878083L;

        private HeaderPanel() {
            add(new JLabel(entry.getName()));
            add(new JLabel(" <"));
            add(new JLabel(entry.getUser()));
            add(new JLabel(">"));
        }
    }

    public static void main(String... args) {
        new ChatDialog(null, null).setVisible(true);
    }
}
